Next: Obsolete Macros, Up: Obsolete Features [Contents][Index]
The following macros are extensions to Common Lisp, where all bindings are lexical unless declared otherwise. These features are likewise obsolete since the introduction of true lexical binding in Emacs 24.1.
This form is exactly like let except that the
bindings it establishes are purely lexical.
Lexical bindings are similar to local variables in a language
like C: Only the code physically within the body of the
lexical-let (after macro expansion) may refer to the
bound variables.
(setq a 5)
(defun foo (b) (+ a b))
(let ((a 2)) (foo a))
⇒ 4
(lexical-let ((a 2)) (foo a))
⇒ 7
In this example, a regular let binding of
a actually makes a temporary change to the global
variable a, so foo is able to see the
binding of a to 2. But lexical-let
actually creates a distinct local variable a for use
within its body, without any effect on the global variable of the
same name.
The most important use of lexical bindings is to create closures. A closure is a function object that refers to an outside lexical variable (see Closures in GNU Emacs Lisp Reference Manual). For example:
(defun make-adder (n)
(lexical-let ((n n))
(function (lambda (m) (+ n m)))))
(setq add17 (make-adder 17))
(funcall add17 4)
⇒ 21
The call (make-adder 17) returns a function
object which adds 17 to its argument. If let had
been used instead of lexical-let, the function
object would have referred to the global n, which
would have been bound to 17 only during the call to
make-adder itself.
(defun make-counter ()
(lexical-let ((n 0))
(cl-function (lambda (&optional (m 1)) (cl-incf n m)))))
(setq count-1 (make-counter))
(funcall count-1 3)
⇒ 3
(funcall count-1 14)
⇒ 17
(setq count-2 (make-counter))
(funcall count-2 5)
⇒ 5
(funcall count-1 2)
⇒ 19
(funcall count-2)
⇒ 6
Here we see that each call to make-counter
creates a distinct local variable n, which serves as
a private counter for the function object that is returned.
Closed-over lexical variables persist until the last reference
to them goes away, just like all other Lisp objects. For example,
count-2 refers to a function object which refers to
an instance of the variable n; this is the only
reference to that variable, so after (setq count-2
nil) the garbage collector would be able to delete this
instance of n. Of course, if a
lexical-let does not actually create any closures,
then the lexical variables are free as soon as the
lexical-let returns.
Many closures are used only during the extent of the bindings
they refer to; these are known as “downward funargs”
in Lisp parlance. When a closure is used in this way, regular
Emacs Lisp dynamic bindings suffice and will be more efficient
than lexical-let closures:
(defun add-to-list (x list)
(mapcar (lambda (y) (+ x y))) list)
(add-to-list 7 '(1 2 5))
⇒ (8 9 12)
Since this lambda is only used while x is still
bound, it is not necessary to make a true closure out of it.
You can use defun or flet inside a
lexical-let to create a named closure. If several
closures are created in the body of a single
lexical-let, they all close over the same instance
of the lexical variable.
This form is just like lexical-let, except
that the bindings are made sequentially in the manner of
let*.
Next: Obsolete Macros, Up: Obsolete Features [Contents][Index]